package br.ufrj.xml.util;

import java.util.Enumeration;
import java.util.Vector;

import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import org.w3c.dom.Document;
import org.w3c.dom.Node;


public class DomToTreeModelAdapter implements TreeModel{
	
	private static final String[] typeName = {
        "none",
        "Element",
        "Attr",
        "Text",
        "CDATA",
        "EntityRef",
        "Entity",
        "ProcInstr",
        "Comment",
        "Document",
        "DocType",
        "DocFragment",
        "Notation",
    };
	
    public class AdapterNode{ 
    	
      Node domNode;

      public AdapterNode(Node node) {
    	  domNode = node;
      }

      public String toString() {
        String s = typeName[domNode.getNodeType()];
        String nodeName = domNode.getNodeName();
        if (! nodeName.startsWith("#")) {
           s += ": " + nodeName;
        }
        if (domNode.getNodeValue() != null) {
           if (s.startsWith("ProcInstr")) 
              s += ", "; 
           else 
              s += ": ";
           
           String t = domNode.getNodeValue().trim();
           int x = t.indexOf("\n");
           if (x >= 0) t = t.substring(0, x);
           s += t;
        }
        return s;
      }

      public int index(AdapterNode child) {
        int count = childCount();
        for (int i=0; i<count; i++) {
          AdapterNode n = this.child(i);
          if (child.domNode == n.domNode) 
        	  return i;
        }
        return -1; 
      }

      public AdapterNode child(int searchIndex) {
        Node node = domNode.getChildNodes().item(searchIndex);
        return new AdapterNode(node); 
      }

      public int childCount() {
          return domNode.getChildNodes().getLength();  
      }
    }
	
    private Vector listenerList = new Vector();
	private Document document; 
	
	public DomToTreeModelAdapter(Document document){
		this.document = document;
	}
	
	public Object  getRoot() {
		return new AdapterNode(document);
	}
  
	public boolean isLeaf(Object aNode) {
		AdapterNode node = (AdapterNode) aNode;
		if (node.childCount() > 0) 
			return false;
		return true;
	}
	
	public int getChildCount(Object parent) {
		AdapterNode node = (AdapterNode) parent;
		return node.childCount();
	}
	
	public Object getChild(Object parent, int index) {
		AdapterNode node = (AdapterNode) parent;
		return node.child(index);
	}
	
	public int getIndexOfChild(Object parent, Object child) {
		AdapterNode node = (AdapterNode) parent;
		return node.index((AdapterNode) child);
	}
	  
	public void valueForPathChanged(TreePath path, Object newValue) {
	}

	public void addTreeModelListener(TreeModelListener listener) {
		if ( listener != null && ! listenerList.contains( listener ) ) {
			listenerList.addElement( listener );
		}
	}
  
	public void removeTreeModelListener(TreeModelListener listener) {
		if ( listener != null ) {
			listenerList.removeElement( listener );
		}
	}

	public void fireTreeNodesChanged( TreeModelEvent e ) {
		Enumeration listeners = listenerList.elements();
		while ( listeners.hasMoreElements() ) {
			TreeModelListener listener = (TreeModelListener) listeners.nextElement();
			listener.treeNodesChanged( e );
		}
	} 
	
	public void fireTreeNodesInserted( TreeModelEvent e ) {
		Enumeration listeners = listenerList.elements();
		while ( listeners.hasMoreElements() ) {
			TreeModelListener listener = (TreeModelListener) listeners.nextElement();
			listener.treeNodesInserted( e );
		}
	}   
	
	public void fireTreeNodesRemoved( TreeModelEvent e ) {
		Enumeration listeners = listenerList.elements();
		while ( listeners.hasMoreElements() ) {
			TreeModelListener listener = (TreeModelListener) listeners.nextElement();
			listener.treeNodesRemoved( e );
		}
	} 

	public void fireTreeStructureChanged( TreeModelEvent e ) {
		Enumeration listeners = listenerList.elements();
		while ( listeners.hasMoreElements() ) {
			TreeModelListener listener = (TreeModelListener) listeners.nextElement();
			listener.treeStructureChanged( e );
		}
	}
}